package librus.cheeseChaser.components
{
	import librus.cheeseChaser.tile.TileModel;
	import librus.cheeseChaser.tile.TileType;
	import librus.cheeseChaser.util.Direction;
	import librus.cheeseChaser.util.Util;

	public class PointEvaluator
	{
		public function PointEvaluator(positionMap:Object, list:Array)
		{
			this.positionMap = positionMap;
			this.list = list;
		}		
		
		public static const TRAPS_LOST_COUNT:int = 3;
		public static const CHEESE_POINT:int = 10;
		public static const CHEESE_GROUP_POINT:int = 20;
		
		protected var list:Array;
		protected var positionMap:Object;
		
		private var __mousePoints:int;
		private var __cheesePoints:int;
		private var __cheeseBonusPoints:int;
		private var __isOver:Boolean;
		
		public function get isOver():Boolean
		{
			return __isOver;
		}

		public function get cheeseBonusPoints():int
		{
			return __cheeseBonusPoints;
		}

		public function get cheesePoints():int
		{
			return __cheesePoints;
		}

		public function get mousePoints():int
		{
			return __mousePoints;
		}

		public function evaluate():void
		{
			var trapList:Array = [];
			var cheeseList:Array = [];
			var mouseList:Array = [];
			
			var item:TileModel;
			
			for (var i:int =0; i <  list.length; i++)
			{
				item = list[i] as TileModel;
				
				switch (item.type.value)
				{
					case TileType.CAT.value:
						handleCat(item);						
						break;
					
					case TileType.TRAP.value:
						trapList.push(item);
						break;
					
					case TileType.CHEESE.value:
						cheeseList.push(item);	
						break;
					
					case TileType.MOUSE_BROWN.value:
					case TileType.MOUSE_GREY.value:
						mouseList.push(item);
						break;
				}
			}
			
			handleTraps(trapList);
			handleCheese(cheeseList);
			handleMouseForBonus(mouseList);
			resetTiles();
		}
		
		protected function handleTraps(trapList:Array):void
		{	
			var activeTraps:int=0;
			var trap:TileModel;
			
			for (var i:int =0 ; i< trapList.length; i++)
			{
				trap = trapList[i] as TileModel;
				
				if (!checkTrap(trap))
					activeTraps++;				
			}
			
			__isOver = activeTraps >= TRAPS_LOST_COUNT;
		}
		
		protected function checkTrap(trap:TileModel):Boolean
		{
			var tileModel:TileModel;
			var direction:Direction;
			var directions:Array = Direction.BASE_DIRECTIONS;
			
			for (var i:int =0 ; i< directions.length; i++)
			{	
				direction = directions[i] as Direction;				
				tileModel = positionMap[Util.pos2Str(trap.position.add(direction.value))] as TileModel;
				
				if (!tileModel || !tileModel.isMouse() || !tileModel.active)
					return false;
			}	
			return true;
		}
		
		protected function handleCheese(cheeseList:Array):void
		{
			__cheesePoints = 0;
			var size:int;
			var cheese:TileModel;
			
			for (var i:int=0;i< cheeseList.length;i++)
			{
				size = 0;
				cheese = cheeseList[i] as TileModel;
				if (cheese.active)
					size = checkCheese(cheese);
				__cheesePoints += size > 1 ? size*CHEESE_GROUP_POINT : size*CHEESE_POINT;
			}
		}
		
		protected function checkCheese(cheese:TileModel):int
		{
			cheese.active = false;
			
			var closedCheeses:int = 0;
			var closedSide:int =0;
			
			var tmp:TileModel;
			
			var direction:Direction;
			var directions:Array = Direction.BASE_DIRECTIONS;
			
			for (var i:int =0 ; i< directions.length; i++)
			{	
				direction = directions[i] as Direction;				
				tmp = positionMap[Util.pos2Str(cheese.position.add(direction.value))] as TileModel;
				
				if (tmp)
				{
					if (tmp.isMouse() && tmp.active || tmp.isCheese() && !tmp.active)
						closedSide++;
					
					if (tmp.isCheese() && tmp.active)
					{
						var tmpCheckCheese:int = checkCheese(tmp);
						closedCheeses += tmpCheckCheese;
						
						if(tmpCheckCheese != 0)
							closedSide++;					
					}
				}				
			}	
			
			if (closedSide >4)
				throw "LOL wtf - more than 4 sides found"
			
			return closedSide >= 4 ? closedCheeses+1 : 0;
		}
		
		protected function handleMouseForBonus(mouseList:Array):void
		{
			__mousePoints = 0;
			__cheeseBonusPoints = 0;
			
			var mouse:TileModel;
			for (var i:int=0; i< mouseList.length;i++)
			{
				mouse = mouseList[i];
				
				if (mouse.active)
				{
					__mousePoints++;
					if (checkMouse(mouse))
						__cheeseBonusPoints++;
				}				
			}
		}
		
		protected function checkMouse(mouse:TileModel):Boolean
		{
			var tileModel:TileModel;
			var direction:Direction;
			var directions:Array = Direction.BASE_DIRECTIONS;
			
			for (var i:int =0 ; i< directions.length; i++)
			{	
				direction = directions[i] as Direction;				
				tileModel = positionMap[Util.pos2Str(mouse.position.add(direction.value))] as TileModel;
				
				if (tileModel && tileModel.isCheese())
					return true;
			}	
			return false;
		}
		
		protected function resetTiles():void
		{			
			for (var i:int =0 ; i< list.length; i++)
				(list[i] as TileModel).reset();			
		}
		
		protected function handleCat(item:TileModel):void
		{	
			var tileModel:TileModel;
			var direction:Direction;
			var directions:Array = Direction.BASE_DIRECTIONS;
			
			for (var i:int =0 ; i< directions.length; i++)
			{	
				direction = directions[i] as Direction;				
				tileModel = positionMap[Util.pos2Str(item.position.add(direction.value))] as TileModel;
			
				if (tileModel && tileModel.isMouse())
					tileModel.active = false;					
			}				
		}
		
	}
}